package znet

import (
	"fmt"
	"net"
	"zinx-learn/utils"
	"zinx-learn/ziface"
)

// Server 服务结构体
type Server struct {
	// 服务器名称
	Name string
	// tcp4 or other
	IPVersion string
	// 服务器绑定的IP
	IP string
	// 服务器绑定的端口
	Port int
	// 路由
	msgHandler ziface.IMsgHandler
	// 连接管理
	connMgr ziface.IConnManager

	//该Server的连接创建时Hook函数
	OnConnStart func(conn ziface.IConnection)
	//该Server的连接断开时的Hook函数
	OnConnStop func(conn ziface.IConnection)
}

func (s *Server) SetOnConnStart(f func(ziface.IConnection)) {
	s.OnConnStart = f
}

func (s *Server) SetOnConnStop(f func(ziface.IConnection)) {
	s.OnConnStop = f
}

func (s *Server) CallOnConnStart(conn ziface.IConnection) {
	if s.OnConnStart != nil {
		fmt.Println("----> CallOnConnStart")
		s.OnConnStart(conn)
	}
}

func (s *Server) CallOnConnStop(conn ziface.IConnection) {
	if s.OnConnStop != nil {
		fmt.Println("----> CallOnStop")
		s.OnConnStop(conn)
	}
}

// Start 方法 实现IServer的Start方法
func (s *Server) Start() {
	fmt.Printf("[Start] Server listenner %s:%d is starting\n", s.IP, s.Port)
	// 开启worker pool
	s.msgHandler.StartWorkerPool()
	// 开启一个goroutine去具体处理业务逻辑
	go func() {
		// 获取ip:port的标准形式
		IPAddr := fmt.Sprintf("%s:%d", s.IP, s.Port)
		addr, err := net.ResolveTCPAddr(s.IPVersion, IPAddr)
		if err != nil {
			fmt.Println("ResolveIPAddr error:", err.Error())
			return
		}
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("err ListenTCP：", err.Error())
			return
		}
		// 监听成功
		fmt.Printf("[Start] Zinx server %s start success !\n", s.Name)
		// 创建ConnectionID
		var cid uint32 = 0
		// 启动server业务
		for {
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Printf("AcceptTcp error %s \n", err.Error())
				continue
			}
			//  设置服务器最大的 连接数，如果超过最大的连接数就关闭这个新的连接
			if s.connMgr.Len() > utils.GlobalObject.MaxConn {
				fmt.Println("[MAXConn] conn is bigger than maxCoon")
				err := conn.Close()
				if err != nil {
					fmt.Println("close connection error ", err.Error())
				}
				// 直接跳出循环 禁止创建连接
				continue
			}
			// 创建Connection连接对象
			cid++
			c := NewConnection(s, conn, cid, s.msgHandler)
			fmt.Printf("[CreatConn] create connection id= %d success !\n", cid)
			// 开启连接处理数据
			go c.Start()
		}
	}()
}

// Stop 方法用于停止服务器
func (s *Server) Stop() {
	fmt.Println("[STOP] zinx server :", s.Name)
	// 其他需要清理的连接的信息或者其他信息
	s.connMgr.ClearConn()
}

// Serve 方法
func (s *Server) Serve() {
	s.Start()
	select {}
}

// AddRouter 添加router路由
func (s *Server) AddRouter(msgId uint32, router ziface.IRouter) {
	s.msgHandler.AddRouter(msgId, router)
}

// GetConnManager 获取连接管理
func (s *Server) GetConnManager() ziface.IConnManager {
	return s.connMgr
}

// NewServer 创建一个新的Server
func NewServer() ziface.IServer {
	s := &Server{
		Name:       utils.GlobalObject.Name,
		IPVersion:  utils.GlobalObject.Version,
		IP:         utils.GlobalObject.Host,
		Port:       utils.GlobalObject.TcpPort,
		msgHandler: NewMsgHandler(),
		connMgr:    NewConnManager(),
	}
	return s
}
